#pragma once
#include <functional>
#include <memory>
#include <set>
#include <utility>
#include "Socket.h"

namespace xncc {
namespace foundation {
    class EventLoop;
    class XnccAddress;
    class Channel;
    class Acceptor
    {
      public:
        using NewConnectionCallback = std::function<void(int, std::shared_ptr<XnccAddress>)>;

        Acceptor(EventLoop* loop, std::shared_ptr<XnccAddress> listenAddr, bool reuseport);
        ~Acceptor();
        Acceptor(const Acceptor&) = delete;

        Acceptor(const Acceptor&&)            = delete;
        Acceptor& operator=(const Acceptor&)  = delete;
        Acceptor& operator=(const Acceptor&&) = delete;

        void init(const std::set<std::string>& blacklist);

        void setNewConnectionCallback(NewConnectionCallback new_conn) { newConnectionCallback_ = std::move(new_conn); }

        [[nodiscard]] bool listenning() const { return listenning_; }
        void               listen();

      private:
        void                     handleRead();
        EventLoop*               loop_;
        std::unique_ptr<Socket>  acceptSocket_;
        std::shared_ptr<Channel> acceptChannel_;  // 和 acceptor的生命周期一样长
        NewConnectionCallback    newConnectionCallback_;
        bool                     listenning_;
        int                      idleFd_;
        std::set<std::string>    blacklist_;
    };
}  // namespace foundation
}  // namespace xncc